//SFC:单文件组件(.vue),SFC组件有自己独立的script、css、html。
/**详细
 * Vue SFC 是一个框架指定的文件格式，
 * 因此必须交由 @vue/compiler-sfc 编译为标准的 JavaScript 和 CSS，
 * 一个编译后的 SFC 是一个标准的 JavaScript(ES) 模块，
 * 这也意味着在构建配置正确的前提下，你可以像导入其他 ES 模块一样导入 SFC
 * 
 * SFC 中的 <style> 标签一般会在开发时注入成原生的 <style> 标签以支持热更新，而生产环境下它们会被抽取、合并成单独的 CSS 文件。
 * 打包时候需要进行整合或抽离css，这需要依赖构建工具(热更新、treeshaking、打包、压缩) 变成一个SPA
 */
//SPA:单页面应用，就是由多个SFC组合成一个页面的应用程序

/**ref实现原理
 * ref(),对传过来的参数做一层包装，包装成一个对象。
 * 里面定义了一个value属性,如果传的是对象,会返回 toReactive(参数) 给value,否则不变(字符串)。
 * 
 * 对象提供了get value和set value方法，去实现依赖收集和更新
 */

/**Vue2和Vue3区别
 * 响应式原理 
 * Object.defineProperty()
 * defineproperty是定义属性的访问器属性，需要遍历每个属性进行监听，还有新增时不会直接变成响应，需要手动初始化对新增属性进行观察  
 * Vue文档建议我们在初始化Vue实例之前，提前初始化data中所有可能用到的属性。
 * 如果想要在Vue实例创建以后添加响应式属性，需要使用Vue.set(object, key, value)，
 * 而不能直接通过赋值来添加新属性（这样添加的新属性不具有响应性）。
 * 
 * new Proxy({},{})  
 * 而proxy是可以代理对象的赋值和获取值的操作，所以动态添加的属性也可以立刻变成响应式。
 * 在get时收集依赖,在set时遍历执行对应属性的所有依赖 
 * 
 * 
 * Vue3性能更好
 *   体积优化：更好的tree-shaking支持，vue3模块重构，采用es modules标准，减少了不必要的代码减少了体积。
 *   编译时优化：1、做了动态内容标记,每次diff的时候只更新需要更新的一小部分，跳过静态内部，从而实现了快速 diff 算法。 (vue2则是遍历找出变化的部分，性能浪费)
 *             2、静态提升：编译时将静态的节点提升出去,组件重新渲染的时候，静态部分直接使用之前编译完成的，而不是重新去创建，只会更新动态的节点。
 * 
 * composition API(更好的灵活性，避免代码逻辑分散，难以维护)
 * 
 * 增强了对TypeScript的支持，使用monorepo代码管理方式,各自独立职责清晰，依赖明确，提高代码可维护性和阅读性
 * 
 * 生命周期api: vue3取消了creted、beforecreate两个生命周期函数，因为被setup函数替代了
 */

/**Vue3声明周期钩子
 * 挂载onMounted、更新onUpdated、销毁onUnmounted
*/

/**computed 和 watch 
 * https://cn.vuejs.org/guide/essentials/computed.html
 * computed属性 一般是依赖于其他响应式数据的，主要是一个经过计算的响应数据。
 * computed本质也是一个ref响应数据，computed接受一个getter函数，然后函数中访问的数据会和这个计算值形成依赖关系，一旦变化也会影响到依赖与这个computed值的程序
 * 如果被依赖的数据不发生变化，那么重复调用仍是上一次getter函数返回的结果，从而提升性能，而方法无法做到这一点。
 * 
 * https://cn.vuejs.org/guide/essentials/watchers.html
 * watch更多的监听某个数据源的变化，然后执行某些操作，比如表单输入时候发起api请求/修改DOM。
 * 可以监听的类型: 响应式对象、computed属性、getter函数、多个源组成的数组
 */
/**Vue模板引用有哪些方式? 
 * 特点:组件挂载完成后才能进行访问，一般onMounted阶段操作
 * 1、普通标签上定义ref属性,声明一个同名ref来存放该元素的引用 <p ref="name">   const name = ref(); 
 * 2、在v-for列表中使用, <p v-for="n in 10" ref="plist">  const plist = ref([])
 * 3、ref还可以作为属性，定义为一个函数，组件更新时会调用 <h1 :ref="console.log"></h1>
 * 4、定义在组件上,可以得到组件实例 
 * （如果一个子组件使用的是选项式 API 或没有使用 <script setup>，被引用的组件实例和该子组件的 this 完全一致，这意味着父组件对子组件的每一个属性和方法都有完全的访问权。）
 *  除非子组件在其中通过 defineExpose 宏显式暴露
*/
/**Vue 组件通信方式有哪些，各有什么特点？
 * https://cn.vuejs.org/guide/components/props.html
 * 
 * 1、在setup的单文件组件中，可使用编译器宏(编译的时候会转换成对应代码)。 
 * 2、如果你没有使用 <script setup>，可以使用 props 选项的方式声明
 * 具体可采用:
 *    - 数组: defineProps(['foo'])
 *    - 对象: defineProps({ title: String, likes: Number })  //推荐,可以设置类型、默认值、必填、自定义类型校验函数【Prop 校验】
 *    - ts类型标注: defineProps<{title:String,name:String}>() 设置默认值比较麻烦,需要另加可以defaultxxx的宏
 * 
 * 衍生知识：
   1、为了方便，可以使用一个对象绑定多个 prop
    const post = {
        id: 1,
        title: 'My Journey with Vue'
    }

    <BlogPost v-bind="post" />
    
    2、单向数据流
    所有的 props 都遵循着单向绑定原则，props 因父组件的更新而变化，避免了子组件意外修改父组件的状态的情况，
    否则应用的数据流将很容易变得混乱而难以理解，所以vue不能在子组件中去更改一个 prop。

*/
/**Vue注册全局组件
 * createApp(App).component('HelloWorld',HelloWorld) 
 * 缺点:tree-shaking无法生效;依赖关系不明确不利于维护
 * 如果没有使用 <script setup>，则需要使用 components 选项来显式注册
 */
//Vue事件修饰符: .stop|.prevent|.self(event.target是元素本身时才会触发)|.once|.capture(捕获阶段先处理)|.passive  url:https://cn.vuejs.org/guide/essentials/event-handling.html
//透传attribute(没有被显示声明的组件props)  file:///E:\newking\Vue\src\components\HelloWorld.vue
//插槽slot有哪几种   file:///E:\newking\Vue\src\components\HelloWorld_1.vue | https://cn.vuejs.org/guide/components/slots.html
/**Vue依赖注入 
 * https://cn.vuejs.org/guide/components/provide-inject.html#prop-drilling
 * 为了解决组件参数props多层组件传递的问题,中间的组件可能不需要这个值,但为了孙组件得到,必须一级一级传递,除非是根节点透传下去。
 * 
 * 使用:
 * //父组件提供依赖   provide('key',value) |  provide('deepprop',{ deepprop,updateDeep }) (可提供参数,和对应的修改方法供子组件调用)
 * //子孙组件注入依赖  inject('key)        |  inject('key','default_value') 
 * 防止注入值被修改:  provide('key',readonly(value))
*/
/**Vue怎么提高项目性能？举一些例子
 * 提升页面加载 和 更新性能 (衡量指标:最大内容绘制-LCP、首次输入延迟-FID)
 * 
 * Vue架构层面:
 * 交互或者实时性要求比较高的，可通过SSR(服务端渲染-页面和数据由后端整合好) 
 * 一些比较固定的页面(关于、文档),可用SSG(静态站点生成器-页面预先生成)的方式部署
 * 
 * Service worker+CacheStorage
 * 使用service worker首次访问时利用fetch监听用户的网络请求，将访问到的资源缓存进cache对象
 * 下次fetch时，做判断如果缓存有就从缓存提取资源，而不去服务器请求。这也是PWA离线应用的实现方式。
 * 
 * 
 * Vue代码层面:
 * 1、减少不必要抽象的组件封装、,因为渲染组件的性能消耗比普通DOM要多。
 * 2、逻辑复用(组合式函数)
 * 3、DOM访问逻辑复用(自定义指令)
 * 4.传递给组件的props尽量保持稳定、 v-once
 * 
 * 
 * 代码分割:(资源懒加载：先加载必要,后视情况加载剩余部分)
 * 1、vue-router路由懒加载（用户访问某个路由再加载相关的组件） 
 * 2、异步组件-按需导入: defineAsyncComponent 需要的时候再异步加载组件(打包时候异步组件会被抽离出来)
 *    异步组件: file:///E:\newking\Vue\src\App.vue
 * 3、虚拟列表(滚动到哪就加载哪部分内容，滚动条虚拟,用户看到哪有心理预期)
 *    优点：如果内容比较复杂，懒加载会很卡，懒加载是累加的过程
 * 4、（预加载：页面加载完后或者设定时间后加载->window.onload 懒加载：执行某操作才加载->onClick...）
 * 
 * 
 * 其他:
 * 1.代码习惯(合理利用循环、即使销毁对象、变量缓存、节流防抖)
 * 2.图片资源压缩 | 使用css字体图标 | 精灵图、base64
 * 3.尽可能使用体积小的工具库，比如用lodash-es替代lodash(es模块依赖,对树摇更友好)|页面交互简单可以用petite-vue替代vue
 * 4.服务器优化(http2协议、代码压缩br|gzip、cdn)
 * 
 * 
 * 负载性能分析工具: WebPageTes、开发者工具的性能面板
*/
/* Vue v-for为什么要指定key
 * Vue 默认按照“就地更新”的策略来更新通过 v-for 渲染的元素列表。
 * 当数据项的顺序改变时，Vue 不会随之移动 DOM 元素的顺序，而是就地更新每个元素，确保它们在原本指定的索引位置上渲染。
 * 为了给 Vue 一个提示，以便它可以跟踪每个节点的标识，从而重用和重新排序现有的元素，你需要为每个元素对应的块提供一个唯一的 key attribute.
 * 如果会变化删除，最好别用index，否则失效也会重新渲染整个列表，最好用唯一的id，做到真正就地更新。
 */
/**自定义指令 (DOM访问逻辑复用)
 * 
 *  //特点: 有独立的声明周期钩子,可以精准触发dom事件,比如异步组件可以用mounted指令钩子,在动态插入元素后生效
 *  //例如input的 autofocus属性就无法做到，因为一开始组件仍未挂载
 * 
 *  常规:
 *  const vFocus = {
 *     mounted(el:HTMLElement,binding:Arguments){ el.focus() },
 *     updated(){}
 *     unmounted(){}
 *     ...
 *  }
 * 
 *  全局(main.js):
 *  app.directive('focus', { //同上 })
 * 
 *  
 *  指令钩子: created | beforeMount | mounted | beforeUpdate | updated | beforeUnmount | unmounted
 *  详细：https://cn.vuejs.org/guide/reusability/custom-directives.html
 *  其他: 不推荐在组件上使用,也会透传，且无法指定传递给某个元素
 */
/**defineExpose-暴露组件属性
    父:
    <Child ref="child" />
    const child = ref<any>(null);    //获取子组件对象
    onMounted(()=>{
        child.value.Loading()
    })

    子:
    defineExpose({
    Loading,orderFunction...
    })
 */
/**插件 - 一种能为 Vue 添加全局功能的工具代码
 * https://cn.vuejs.org/guide/reusability/plugins.html
 * file:///E:\newking\Vue\src\plugins\test.ts
 * 
 * export default {
     install(app:App,options:any){
        app.config.globalProperties.$translate = (key:any, value:any) => {
            return options[key][value]
        }
        app.provide('alllang', options)
     }
}
 * 
 */
/**内置组件
 * Transition-过渡动画
 * TransitonGroup-循环列表过渡动画
 * KeepAlive-动态组件切换时保留原组件实例状态
 * Teleport-传送节点  E:\newking\Vue\src\components\Dialog.vue
 */
//SSR服务端渲染，需要node环境支持 | SSG 静态站点生成(适用于所有用户访问都是相同的,不需要经常重新部署的) : vitepress 
/**JSX
 * JSX是由FaceBook提出的，用在React中，通过Babel插件解析jsx(es6->es5,jsx->js)，Babel也是FaceBook的一个工程师写的
 * Vite中是通过安装 "@vue/babel-plugin-jsx" 这个babel插件，实现对jsx语法的解析的。
 */


// element ui table 吸顶怎么做，滚动怎么处理等


// https://cn.vuejs.org/guide/best-practices/performance.html 